package com.atguigu.bookcity.realm;

import com.atguigu.bookcity.utils.RedisUtil;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


import javax.annotation.Resource;

@Component
public class CustomHashedCredentialsMatcher extends HashedCredentialsMatcher {
    //这个是redis里的key的统一前缀
    private static final String PREFIX = "USER_LOGIN_FAIL:";

    //yml 中指定密码错误上限
    @Value("${shiro.error}")
    private Integer passwordErrorTimes;

    @Resource
    RedisUtil redisUtil;

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {

        //检查本账号是否被冻结

        //先获取用户的登录名字
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;

        String userName = userToken.getUsername();

        //初始化错误登录次数
        int errorNum = 0;

        //从数据库里获取错误次数
        String errorTimes = (String) redisUtil.get(PREFIX + userName);

        if (errorTimes != null && errorTimes.trim().length() > 0) {
            //如果得到的字符串不为空
            errorNum = Integer.parseInt(errorTimes);
        }

        //如果用户连续错误登录次数超过  系统指定次数
        if (errorNum >= passwordErrorTimes) {
            //抛出账号锁定异常类
            throw new ExcessiveAttemptsException();
        }

        //先按照父类的规则来比对密码
        boolean matched = super.doCredentialsMatch(token, info);

        if (matched) {
            //清空错误次数
            redisUtil.del(PREFIX + userName);
        } else {
            //添加一次错误次数  秒为单位
            redisUtil.set(PREFIX + userName, String.valueOf(++errorNum), 60 * 30L);
        }

        return matched;
    }

}
